package com.jkj.http.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgentUtil;
import com.jkj.http.entity.Keys;
import com.jkj.http.entity.Level;
import com.jkj.http.entity.Operator;
import com.jkj.http.interceptor.LoginChecked;
import com.jkj.http.sys.entity.SysUser;
import com.jkj.http.sys.entity.SysUserLogOn;
import com.jkj.http.sys.service.AccountService;
import com.jkj.http.sys.service.LogService;
import com.jkj.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.UUID;

@RestController
public class AccountController extends BaseController {
    @Value("${filePath}")
    private String filePath;
    @Value("${softwareName}")
    private String softwareName;
    @Autowired(required = true)
    private AccountService accountService;
    @Autowired(required = true)
    private LogService logService;

    /**
     * 用户登录页面
     *
     * @return
     */
    @RequestMapping(value = {"/", "/index", "/account/login", "/login", "/admin"}, method = {RequestMethod.GET})
    public ModelAndView login() {
        ModelAndView view = new ModelAndView();
        view.addObject("SoftwareName", softwareName);
        view.setViewName("system/account/login");
        return view;
    }

    /**
     * 获取验证码图片
     *
     * @param request
     * @param response
     * @param session
     * @throws IOException
     */
    @RequestMapping(value = "/account/verifyCode", method = {RequestMethod.GET})
    public void verifyCode(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
        //定义图形验证码的长、宽、验证码字符数、干扰元素个数
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(63, 37, 4, 5);
        session.setAttribute(Keys.SESSION_KEY_VCODE, captcha.getCode().toLowerCase());
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        captcha.write(response.getOutputStream());
        response.getOutputStream().flush();
    }

    /**
     * 登录功能
     *
     * @param userName
     * @param password
     * @param verifyCode
     * @return
     */
    @RequestMapping(value = "/account/login", method = {RequestMethod.POST}, produces = "application/json; charset=utf-8")
    public String login(HttpServletRequest request, @RequestParam("userName") String userName, @RequestParam("password") String password, @RequestParam("verifyCode") String verifyCode) {
        if (StrUtil.isEmpty(userName) || StrUtil.isEmpty(password) || StrUtil.isEmpty(verifyCode)) {
            return error("请求失败，缺少必要参数。");
        }
        if (!verifyCode.toLowerCase().equals(request.getSession().getAttribute(Keys.SESSION_KEY_VCODE))) {
            return warning("验证码错误，请重新输入。");
        }
        SysUser userEntity = accountService.getByUserName(userName);
        if (userEntity == null) {
            return warning("该账户不存在，请重新输入。");
        }
        if (!userEntity.getIsEnabled().equals("1")) {
            return warning("该账户已被禁用，请联系管理员。");
        }
        SysUserLogOn userLogOnEntity = accountService.getByAccount(userEntity.getId());
        String inputPassword = SecureUtil.md5(Encrypt.DESEncrypt(password, userLogOnEntity.getSecretKey())).toLowerCase();
        if (!inputPassword.equals(userLogOnEntity.getPassword())) {
            logService.write(Level.Info, "系统登录", "密码错误", userEntity.getAccount(), userEntity.getRealName(), ServletUtil.getClientIP(request), UserAgentUtil.parse(request.getHeader("User-Agent")).getBrowser().toString());
            return warning("密码错误，请重新输入。");
        } else {
            Operator operatorModel = new Operator();
            operatorModel.setUserId(userEntity.getId());
            operatorModel.setAccount(userEntity.getAccount());
            operatorModel.setRealName(userEntity.getRealName());
            operatorModel.setAvatar(userEntity.getAvatar());
            operatorModel.setCompanyId(userEntity.getCompanyId());
            operatorModel.setDepartmentId(userEntity.getDepartmentId());
            operatorModel.setLoginTime(new Date());
            operatorModel.setToken(Encrypt.DESEncrypt(UUID.randomUUID().toString().replaceAll("-", "")));
            request.getSession().setAttribute("LoginUser", Encrypt.DESEncrypt(JsonUtils.toJSON(operatorModel)));
            accountService.updateLogin(userLogOnEntity);
            logService.write(Level.Info, "系统登录", "登录成功", userEntity.getAccount(), userEntity.getRealName(), ServletUtil.getClientIP(request), UserAgentUtil.parse(request.getHeader("User-Agent")).getBrowser().toString());
            return success();
        }
    }

    /**
     * 登录功能
     *
     * @param userName
     * @param password
     * @return
     */
    @RequestMapping(value = "/app/login", method = {RequestMethod.POST}, produces = "application/json; charset=utf-8")
    public String appLogin(HttpServletRequest request, @RequestParam("userName") String userName, @RequestParam("password") String password) {
        if (StrUtil.isEmpty(userName) || StrUtil.isEmpty(password)) {
            return error("请求失败，缺少必要参数。");
        }
        SysUser userEntity = accountService.getByUserName(userName);
        if (userEntity == null) {
            return warning("该账户不存在，请重新输入。");
        }
        if (!userEntity.getIsEnabled().equals("1")) {
            return warning("该账户已被禁用，请联系管理员。");
        }
        SysUserLogOn userLogOnEntity = accountService.getByAccount(userEntity.getId());
        String inputPassword = SecureUtil.md5(Encrypt.DESEncrypt(password, userLogOnEntity.getSecretKey())).toLowerCase();
        if (!inputPassword.equals(userLogOnEntity.getPassword())) {
            logService.write(Level.Info, "系统登录", "密码错误", userEntity.getAccount(), userEntity.getRealName(), ServletUtil.getClientIP(request), UserAgentUtil.parse(request.getHeader("User-Agent")).getBrowser().toString());
            return warning("密码错误，请重新输入。");
        } else {
            Operator operatorModel = new Operator();
            operatorModel.setUserId(userEntity.getId());
            operatorModel.setAccount(userEntity.getAccount());
            operatorModel.setRealName(userEntity.getRealName());
            operatorModel.setAvatar(userEntity.getAvatar());
            operatorModel.setCompanyId(userEntity.getCompanyId());
            operatorModel.setDepartmentId(userEntity.getDepartmentId());
            operatorModel.setLoginTime(new Date());
            operatorModel.setToken(Encrypt.DESEncrypt(UUID.randomUUID().toString().replaceAll("-", "")));
            request.getSession().setAttribute("LoginUser", Encrypt.DESEncrypt(JsonUtils.toJSON(operatorModel)));
            accountService.updateLogin(userLogOnEntity);
            logService.write(Level.Info, "系统登录", "登录成功", userEntity.getAccount(), userEntity.getRealName(), ServletUtil.getClientIP(request), UserAgentUtil.parse(request.getHeader("User-Agent")).getBrowser().toString());
            return success();
        }
    }


    /**
     * 退出登录
     *
     * @param session
     * @return
     */
    @RequestMapping(value = "/account/exit", method = {RequestMethod.GET})
    public ModelAndView exit(HttpSession session) {
        if (OperatorProvider.getCurrent(session) != null) {
            OperatorProvider.remove(session);
        }
        ModelAndView view = new ModelAndView();
        view.addObject("SoftwareName", softwareName);
        view.setViewName("system/account/login");
        return view;
    }

    /**
     * 锁定登录用户
     *
     * @param session
     * @return
     */
    @LoginChecked()
    @RequestMapping(value = "/account/lock", method = {RequestMethod.POST}, produces = "application/json; charset=utf-8")
    public String lock(HttpSession session) {
        if (OperatorProvider.getCurrent(session) != null) {
            OperatorProvider.remove(session);
        }
        return success();
    }

    /**
     * 解锁用户登录
     *
     * @param session
     * @param username
     * @param password
     * @return
     */
    @RequestMapping(value = "/account/unlock", method = {RequestMethod.POST}, produces = "application/json; charset=utf-8")
    public String unlock(HttpSession session, String username, String password) {
        SysUser userEntity = accountService.getByUserName(username);
        SysUserLogOn userLogOnEntity = accountService.getByAccount(userEntity.getId());
        String inputPassword = SecureUtil.md5(Encrypt.DESEncrypt(password, userLogOnEntity.getSecretKey())).toLowerCase();
        if (!inputPassword.equals(userLogOnEntity.getPassword())) {
            return warning("密码错误，请重新输入。");
        } else {
            // 重新保存用户信息。
            Operator operatorModel = new Operator();
            operatorModel.setUserId(userEntity.getId());
            operatorModel.setAccount(userEntity.getAccount());
            operatorModel.setRealName(userEntity.getRealName());
            operatorModel.setAvatar(userEntity.getAvatar());
            operatorModel.setCompanyId(userEntity.getCompanyId());
            operatorModel.setDepartmentId(userEntity.getDepartmentId());
            operatorModel.setLoginTime(new Date());
            operatorModel.setToken(Encrypt.DESEncrypt(UUID.randomUUID().toString().replaceAll("-", "")));
            session.setAttribute("LoginUser", Encrypt.DESEncrypt(JsonUtils.toJSON(operatorModel)));
        }
        return success();
    }

    /**
     * 用户账户管理视图
     *
     * @return
     */
    @LoginChecked()
    @RequestMapping(value = "/account/infoCard", method = {RequestMethod.GET})
    public ModelAndView infoCard() {
        return new ModelAndView("system/account/infoCard");
    }

    /**
     * 用户信息修改
     *
     * @param model
     * @return
     */
    @LoginChecked()
    @RequestMapping(value = "/account/infoCard", method = {RequestMethod.POST}, produces = "application/json; charset=utf-8")
    public String infoCard(SysUser model) {
        try {
            Date defaultDt = DateUtil.parse(model.getStrBirthDay());
            ;
            model.setBirthday(defaultDt);
            int row = accountService.updateBasicInfo(model);
            return row > 0 ? success() : error();
        } catch (Exception e) {
            return error();
        }
    }

    /**
     * 获得用户信息
     *
     * @param session
     * @return
     */
    @LoginChecked()
    @RequestMapping(value = "/account/getInfoCardForm", method = {RequestMethod.POST}, produces = "application/json; charset=utf-8")
    public String getInfoCardForm(HttpSession session) {
        String userId = OperatorProvider.getCurrent(session).getUserId();
        SysUser userEntity = accountService.getUser(userId);
        return JsonUtils.toJSON(userEntity);
    }

    /**
     * 上传头像。
     *
     * @param file
     * @param request
     * @return
     */
    @RequestMapping(value = "/account/uploadAvatar", method = {RequestMethod.POST}, produces = "application/json; charset=utf-8")
    public String uploadAvatar(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) {
        if (file == null)
            return error();
        if (file.isEmpty())
            return error();
        String ext = file.getOriginalFilename().substring(file.getOriginalFilename().indexOf("."));// 取文件格式后缀名
        String fileName = UUID.randomUUID().toString().replace("-", "") + ext;
        String virtualPath = "/Uploads/Avatar/" + fileName;
        String rootPath = filePath;
        if (!rootPath.endsWith("/"))
            rootPath += "/";
        String uploadDir = rootPath + "Uploads/";
        File uploadDirFile = new File(uploadDir);
        if (!uploadDirFile.exists()) {
            uploadDirFile.mkdirs();
        }
        String avatarPath = uploadDir + "Avatar/";
        File avatarPathFile = new File(avatarPath);
        if (!avatarPathFile.exists()) {
            avatarPathFile.mkdirs();
        }
        String path = avatarPath + fileName;// 存放位置
        File destFile = new File(path);
        if (destFile.exists()) {
            destFile.delete();
        }
        try {
            file.transferTo(destFile);
            return success("上传成功。", virtualPath);
        } catch (IOException e) {
            return error();
        }
    }

    /**
     * 上传图片
     *
     * @param file
     * @param request
     * @return
     */
    @RequestMapping(value = "/account/uploadImage", method = {RequestMethod.POST}, produces = "application/json; charset=utf-8")
    public String uploadImage(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) {
        if (file == null)
            return error();
        if (file.isEmpty())
            return error();
        String ext = file.getOriginalFilename().substring(file.getOriginalFilename().indexOf("."));// 取文件格式后缀名
        String fileName = UUID.randomUUID().toString().replace("-", "") + ext;
        String virtualPath = "/Uploads/Avatar/" + fileName;
        String rootPath = filePath;
        if (!rootPath.endsWith("/"))
            rootPath += "/";
        String uploadDir = rootPath + "Uploads/";
        File uploadDirFile = new File(uploadDir);
        if (!uploadDirFile.exists()) {
            uploadDirFile.mkdirs();
        }
        String avatarPath = uploadDir + "Avatar/";
        File avatarPathFile = new File(avatarPath);
        if (!avatarPathFile.exists()) {
            avatarPathFile.mkdirs();
        }
        String path = avatarPath + fileName;// 存放位置
        File destFile = new File(path);
        if (destFile.exists()) {
            destFile.delete();
        }
        try {
            file.transferTo(destFile);
            return success("上传成功。", virtualPath);
        } catch (IOException e) {
            return error();
        }
    }

    /**
     * 修改密码画面
     *
     * @return
     */
    @LoginChecked()
    @RequestMapping(value = "/account/modifyPwd", method = {RequestMethod.GET})
    public ModelAndView modifyPwd() {
        return new ModelAndView("system/account/modifyPwd");
    }

    /**
     * 修改密码
     *
     * @param session
     * @param oldPassword
     * @param newPassword
     * @param confirmPassword
     * @return
     */
    @LoginChecked()
    @RequestMapping(value = "/account/modifyPwd", method = {RequestMethod.POST}, produces = "application/json; charset=utf-8")
    public String modifyPwd(HttpSession session, String oldPassword, String newPassword, String confirmPassword) {
        if (StrUtil.isEmpty(oldPassword) || StrUtil.isEmpty(newPassword) || StrUtil.isEmpty(confirmPassword)) {
            return error("请求失败，缺少必要参数。");
        }
        if (!newPassword.equals(confirmPassword)) {
            return warning("两次密码输入不一致，请重新确认。");
        }
        String userId = OperatorProvider.getCurrent(session).getUserId();
        SysUserLogOn userLoginEntity = accountService.getByAccount(userId);
        if (!SecureUtil.md5(Encrypt.DESEncrypt(oldPassword, userLoginEntity.getSecretKey())).toLowerCase().equals(userLoginEntity.getPassword())) {
            return warning("旧密码验证失败。");
        }
        userLoginEntity.setPassword(SecureUtil.md5(Encrypt.DESEncrypt(newPassword, userLoginEntity.getSecretKey())).toLowerCase());
        int flag = accountService.modifyPwd(userLoginEntity);
        return flag > 0 ? success() : error();
    }
}
